package com.gitee.sparta.core.bean.metadata;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.gitee.sparta.common.SpartaConstant;
import lombok.Getter;
import lombok.Setter;

import java.io.Serializable;
import java.util.Set;

/**
 * 消息元数据
 *  body 字段包含的是用户提交的内容
 *
 * @param <V>
 * @author zyred
 * @since v 0.0.1
 */
@Setter
@Getter
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
public class Metadata<V> implements Serializable {
    private static final long serialVersionUID = -5802087359793973198L;

    /** 元数据 ID，UUID，全局唯一，该 ID 会通过 Channel 提供给用户 **/
    private String metaId;

    /** 消息所在的 topic **/
    private String topic;

    /**
     * 过期时间, 单位：ms
     * 例如：消息需要延迟 10s 过期，那这里的值就是 10000
     */
    private long expire;

    /**
     * 用于临时存储分段消费的时间节点
     * 该内容不会被序列化到 json 中，主要是
     * 用来内部处理业务的时候使用的，主要是区分
     * 是普通的写入还是分段写入的关键因素
     *
     * <p>
     * 如果用户调用的是 {@see TimeoutTabOperate#writeAsync(String, Object, List)}
     * 的写入 api，则该值是 List 的所有时间节点
     */
    @JsonIgnore
    private transient Set<Long> segments;

    /** 重试次数：该值表示调用用户的业务执行失败后，执行了重试的次数记录 **/
    private int retryNumber = 0;

    /** 续期次数：该值表示用户在业务中调用了续签的 api 后的次数记录 **/
    private int renewNumber = 0;

    /**
     * 重试间隔时间，单位：ms
     * 默认：3s
     * 将重试时间交给用户
     */
    private int retryIntervalTime = SpartaConstant.RETRY_INTERVAL;

    /**
     * 续签时间
     * 默认 30s
     * 将续签间隔时间交给用户
     */
    private int renewIntervalTime = SpartaConstant.RENEW_INTERVAL;

    /**
     * 一次插入，多次消费的时间的总个数
     * 例如：任务在 1s，2s，3s，4s，5s 的时候被消费，那么这个数的大小则是 5
     * {@see SpartaTemplate#write(String, Object, Set)}
     * 批量提交的时候, 记录执行的标记
     */
    private int segmentSize;

    /**
     * 消息体，任意类型数据
     */
    @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
    private V body;

    /**
     * 是否是广播，用于消息过期后的使用
     * @since v 0.0.2
     */
    private boolean broadcast;

    @JsonIgnore
    public boolean isSegment () {
        return this.segmentSize > 0;
    }
}
